<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Video Input with OpenCV and similarity measurement</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d9/df8/tutorial_root.html">OpenCV Tutorials</a></li><li class="navelem"><a class="el" href="../../de/d3d/tutorial_table_of_content_app.html">Application utils (highgui, imgcodecs, videoio modules)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Video Input with OpenCV and similarity measurement </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><b>Prev Tutorial:</b> <a class="el" href="../../d7/d73/tutorial_raster_io_gdal.html">Reading Geospatial Raster files with GDAL</a></p>
<p><b>Next Tutorial:</b> <a class="el" href="../../d7/d9e/tutorial_video_write.html">Creating a video with OpenCV</a></p>
<table class="doxtable">
<tr>
<th align="right"></th><th align="left"></th></tr>
<tr>
<td align="right">Original author </td><td align="left">Bernát Gábor </td></tr>
<tr>
<td align="right">Compatibility </td><td align="left">OpenCV &gt;= 3.0 </td></tr>
</table>
<h2>Goal </h2>
<p>Today it is common to have a digital video recording system at your disposal. Therefore, you will eventually come to the situation that you no longer process a batch of images, but video streams. These may be of two kinds: real-time image feed (in the case of a webcam) or prerecorded and hard disk drive stored files. Luckily OpenCV treats these two in the same manner, with the same C++ class. So here's what you'll learn in this tutorial:</p>
<ul>
<li>How to open and read video streams</li>
<li>Two ways for checking image similarity: PSNR and SSIM</li>
</ul>
<h2>The source code </h2>
<p>As a test case where to show off these using OpenCV I've created a small program that reads in two video files and performs a similarity check between them. This is something you could use to check just how well a new video compressing algorithms works. Let there be a reference (original) video like <a href="https://github.com/opencv/opencv/tree/master/samples/data/Megamind.avi">this small Megamind clip</a> and <a href="https://github.com/opencv/opencv/tree/master/samples/data/Megamind_bugy.avi">a compressed version of it</a>. You may also find the source code and these video file in the <code>samples/data</code> folder of the OpenCV source library.</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line"><span class="preprocessor">#include &lt;iostream&gt;</span> <span class="comment">// for standard I/O</span></div><div class="line"><span class="preprocessor">#include &lt;string&gt;</span>   <span class="comment">// for strings</span></div><div class="line"><span class="preprocessor">#include &lt;iomanip&gt;</span>  <span class="comment">// for controlling float print precision</span></div><div class="line"><span class="preprocessor">#include &lt;sstream&gt;</span>  <span class="comment">// string to number conversion</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d0/d9c/core_2include_2opencv2_2core_8hpp.html">opencv2/core.hpp</a>&gt;</span>     <span class="comment">// Basic OpenCV structures (cv::Mat, Scalar)</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d1/d4f/imgproc_2include_2opencv2_2imgproc_8hpp.html">opencv2/imgproc.hpp</a>&gt;</span>  <span class="comment">// Gaussian Blur</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../dc/d3d/videoio_8hpp.html">opencv2/videoio.hpp</a>&gt;</span></div><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="../../d4/dd5/highgui_8hpp.html">opencv2/highgui.hpp</a>&gt;</span>  <span class="comment">// OpenCV window I/O</span></div><div class="line"></div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d8/dcc/namespacestd.html">std</a>;</div><div class="line"><span class="keyword">using namespace </span><a class="code" href="../../d2/d75/namespacecv.html">cv</a>;</div><div class="line"></div><div class="line"><span class="keywordtype">double</span> getPSNR ( <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I1, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I2);</div><div class="line"><a class="code" href="../../d1/da0/classcv_1_1Scalar__.html">Scalar</a> getMSSIM( <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I1, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I2);</div><div class="line"></div><div class="line"><span class="keyword">static</span> <span class="keywordtype">void</span> help()</div><div class="line">{</div><div class="line">    cout</div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;------------------------------------------------------------------------------&quot;</span> &lt;&lt; endl</div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;This program shows how to read a video file with OpenCV. In addition, it &quot;</span></div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;tests the similarity of two input videos first with PSNR, and for the frames &quot;</span></div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;below a PSNR trigger value, also with MSSIM.&quot;</span>                                   &lt;&lt; endl</div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;Usage:&quot;</span>                                                                         &lt;&lt; endl</div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;./video-input-psnr-ssim &lt;referenceVideo&gt; &lt;useCaseTestVideo&gt; &lt;PSNR_Trigger_Value&gt; &lt;Wait_Between_Frames&gt; &quot;</span> &lt;&lt; endl</div><div class="line">        &lt;&lt; <span class="stringliteral">&quot;--------------------------------------------------------------------------&quot;</span>     &lt;&lt; endl</div><div class="line">        &lt;&lt; endl;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span> *argv[])</div><div class="line">{</div><div class="line">    help();</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (argc != 5)</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Not enough parameters&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    stringstream conv;</div><div class="line"></div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">string</span> sourceReference = argv[1], sourceCompareWith = argv[2];</div><div class="line">    <span class="keywordtype">int</span> psnrTriggerValue, delay;</div><div class="line">    conv &lt;&lt; argv[3] &lt;&lt; endl &lt;&lt; argv[4];       <span class="comment">// put in the strings</span></div><div class="line">    conv &gt;&gt; psnrTriggerValue &gt;&gt; delay;        <span class="comment">// take out the numbers</span></div><div class="line"></div><div class="line">    <span class="keywordtype">int</span> frameNum = -1;          <span class="comment">// Frame counter</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">VideoCapture</a> captRefrnc(sourceReference), captUndTst(sourceCompareWith);</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (!captRefrnc.isOpened())</div><div class="line">    {</div><div class="line">        cout  &lt;&lt; <span class="stringliteral">&quot;Could not open reference &quot;</span> &lt;&lt; sourceReference &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (!captUndTst.isOpened())</div><div class="line">    {</div><div class="line">        cout  &lt;&lt; <span class="stringliteral">&quot;Could not open case test &quot;</span> &lt;&lt; sourceCompareWith &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <a class="code" href="../../d6/d50/classcv_1_1Size__.html">Size</a> refS = <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>((<span class="keywordtype">int</span>) captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dab26d2ba37086662261148e9fe93eecad">CAP_PROP_FRAME_WIDTH</a>),</div><div class="line">                     (int) captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dad8b57083fd9bd58e0f94e68a54b42b7e">CAP_PROP_FRAME_HEIGHT</a>)),</div><div class="line">         uTSi = <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>((<span class="keywordtype">int</span>) captUndTst.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dab26d2ba37086662261148e9fe93eecad">CAP_PROP_FRAME_WIDTH</a>),</div><div class="line">                     (int) captUndTst.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dad8b57083fd9bd58e0f94e68a54b42b7e">CAP_PROP_FRAME_HEIGHT</a>));</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (refS != uTSi)</div><div class="line">    {</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Inputs have different size!!! Closing.&quot;</span> &lt;&lt; endl;</div><div class="line">        <span class="keywordflow">return</span> -1;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">char</span>* WIN_UT = <span class="stringliteral">&quot;Under Test&quot;</span>;</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">char</span>* WIN_RF = <span class="stringliteral">&quot;Reference&quot;</span>;</div><div class="line"></div><div class="line">    <span class="comment">// Windows</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>(WIN_RF, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3acf621ace7a54954cbac01df27e47228f">WINDOW_AUTOSIZE</a>);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">namedWindow</a>(WIN_UT, <a class="code" href="../../d0/d90/group__highgui__window__flags.html#ggabf7d2c5625bc59ac130287f925557ac3acf621ace7a54954cbac01df27e47228f">WINDOW_AUTOSIZE</a>);</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>(WIN_RF, 400       , 0);         <span class="comment">//750,  2 (bernat =0)</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">moveWindow</a>(WIN_UT, refS.<a class="code" href="../../d6/d50/classcv_1_1Size__.html#abfe0367b32c407ddccf5ddf92667c73d">width</a>, 0);         <span class="comment">//1500, 2</span></div><div class="line"></div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;Reference frame resolution: Width=&quot;</span> &lt;&lt; refS.<a class="code" href="../../d6/d50/classcv_1_1Size__.html#abfe0367b32c407ddccf5ddf92667c73d">width</a> &lt;&lt; <span class="stringliteral">&quot;  Height=&quot;</span> &lt;&lt; refS.<a class="code" href="../../d6/d50/classcv_1_1Size__.html#a1d289dce6b5d8006a54f3ee0259fc545">height</a></div><div class="line">         &lt;&lt; <span class="stringliteral">&quot; of nr#: &quot;</span> &lt;&lt; captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dadadc646b31cfd2194794a3a80b8fa6c2">CAP_PROP_FRAME_COUNT</a>) &lt;&lt; endl;</div><div class="line"></div><div class="line">    cout &lt;&lt; <span class="stringliteral">&quot;PSNR trigger value &quot;</span> &lt;&lt; setiosflags(ios::fixed) &lt;&lt; setprecision(3)</div><div class="line">         &lt;&lt; psnrTriggerValue &lt;&lt; endl;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> frameReference, frameUnderTest;</div><div class="line">    <span class="keywordtype">double</span> psnrV;</div><div class="line">    <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html">Scalar</a> mssimV;</div><div class="line"></div><div class="line">    <span class="keywordflow">for</span>(;;) <span class="comment">//Show the image captured in the window and repeat</span></div><div class="line">    {</div><div class="line">        captRefrnc &gt;&gt; frameReference;</div><div class="line">        captUndTst &gt;&gt; frameUnderTest;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (frameReference.empty() || frameUnderTest.empty())</div><div class="line">        {</div><div class="line">            cout &lt;&lt; <span class="stringliteral">&quot; &lt; &lt; &lt;  Game over!  &gt; &gt; &gt; &quot;</span>;</div><div class="line">            <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        ++frameNum;</div><div class="line">        cout &lt;&lt; <span class="stringliteral">&quot;Frame: &quot;</span> &lt;&lt; frameNum &lt;&lt; <span class="stringliteral">&quot;# &quot;</span>;</div><div class="line"></div><div class="line">        psnrV = getPSNR(frameReference,frameUnderTest);</div><div class="line">        cout &lt;&lt; setiosflags(ios::fixed) &lt;&lt; setprecision(3) &lt;&lt; psnrV &lt;&lt; <span class="stringliteral">&quot;dB&quot;</span>;</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (psnrV &lt; psnrTriggerValue &amp;&amp; psnrV)</div><div class="line">        {</div><div class="line">            mssimV = getMSSIM(frameReference, frameUnderTest);</div><div class="line"></div><div class="line">            cout &lt;&lt; <span class="stringliteral">&quot; MSSIM: &quot;</span></div><div class="line">                &lt;&lt; <span class="stringliteral">&quot; R &quot;</span> &lt;&lt; setiosflags(ios::fixed) &lt;&lt; setprecision(2) &lt;&lt; mssimV.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[2] * 100 &lt;&lt; <span class="stringliteral">&quot;%&quot;</span></div><div class="line">                &lt;&lt; <span class="stringliteral">&quot; G &quot;</span> &lt;&lt; setiosflags(ios::fixed) &lt;&lt; setprecision(2) &lt;&lt; mssimV.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[1] * 100 &lt;&lt; <span class="stringliteral">&quot;%&quot;</span></div><div class="line">                &lt;&lt; <span class="stringliteral">&quot; B &quot;</span> &lt;&lt; setiosflags(ios::fixed) &lt;&lt; setprecision(2) &lt;&lt; mssimV.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[0] * 100 &lt;&lt; <span class="stringliteral">&quot;%&quot;</span>;</div><div class="line">        }</div><div class="line"></div><div class="line">        cout &lt;&lt; endl;</div><div class="line"></div><div class="line">        <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(WIN_RF, frameReference);</div><div class="line">        <a class="code" href="../../d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563">imshow</a>(WIN_UT, frameUnderTest);</div><div class="line"></div><div class="line">        <span class="keywordtype">char</span> c = (char)<a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">waitKey</a>(delay);</div><div class="line">        <span class="keywordflow">if</span> (c == 27) <span class="keywordflow">break</span>;</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keywordflow">return</span> 0;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">// ![get-psnr]</span></div><div class="line"><span class="keywordtype">double</span> getPSNR(<span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I1, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; I2)</div><div class="line">{</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> s1;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6fef31bc8c4071cbc114a758a2b79c14">absdiff</a>(I1, I2, s1);       <span class="comment">// |I1 - I2|</span></div><div class="line">    s1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(s1, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>);  <span class="comment">// cannot make a square on 8 bits</span></div><div class="line">    s1 = s1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(s1);           <span class="comment">// |I1 - I2|^2</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html">Scalar</a> s = <a class="code" href="../../d2/de8/group__core__array.html#ga716e10a2dd9e228e4d3c95818f106722">sum</a>(s1);        <span class="comment">// sum elements per channel</span></div><div class="line"></div><div class="line">    <span class="keywordtype">double</span> sse = s.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[0] + s.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[1] + s.<a class="code" href="../../de/de1/classcv_1_1Matx.html#afa9ad3bc5b09ebcdfc6f98f44c15191d">val</a>[2]; <span class="comment">// sum channels</span></div><div class="line"></div><div class="line">    <span class="keywordflow">if</span>( sse &lt;= 1e-10) <span class="comment">// for small values return zero</span></div><div class="line">        <span class="keywordflow">return</span> 0;</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">        <span class="keywordtype">double</span> mse  = sse / (double)(I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa11336b9ac538e0475d840657ce164be">channels</a>() * I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#aa4d317d43fb0cba9c2503f3c61b866c8">total</a>());</div><div class="line">        <span class="keywordtype">double</span> psnr = 10.0 * <a class="code" href="../../df/dfc/group__cudev.html#ga6d7f752d82c289caa24bbb5a278ac31d">log10</a>((255 * 255) / mse);</div><div class="line">        <span class="keywordflow">return</span> psnr;</div><div class="line">    }</div><div class="line">}</div><div class="line"><span class="comment">// ![get-psnr]</span></div><div class="line"></div><div class="line"><span class="comment">// ![get-mssim]</span></div><div class="line"></div><div class="line"><a class="code" href="../../d1/da0/classcv_1_1Scalar__.html">Scalar</a> getMSSIM( <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; i1, <span class="keyword">const</span> <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a>&amp; i2)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">double</span> C1 = 6.5025, C2 = 58.5225;</div><div class="line">    <span class="comment">/***************************** INITS **********************************/</span></div><div class="line">    <span class="keywordtype">int</span> d = <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> I1, I2;</div><div class="line">    i1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(I1, d);            <span class="comment">// cannot calculate on one byte large values</span></div><div class="line">    i2.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#adf88c60c5b4980e05bb556080916978b">convertTo</a>(I2, d);</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> I2_2   = I2.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I2);        <span class="comment">// I2^2</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> I1_2   = I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I1);        <span class="comment">// I1^2</span></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> I1_I2  = I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I2);        <span class="comment">// I1 * I2</span></div><div class="line"></div><div class="line">    <span class="comment">/*************************** END INITS **********************************/</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> mu1, mu2;                   <span class="comment">// PRELIMINARY COMPUTING</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1, mu1, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I2, mu2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> mu1_2   =   mu1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu1);</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> mu2_2   =   mu2.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu2);</div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> mu1_mu2 =   mu1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu2);</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> sigma1_2, sigma2_2, sigma12;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1_2, sigma1_2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma1_2 -= mu1_2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I2_2, sigma2_2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma2_2 -= mu2_2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1_I2, sigma12, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma12 -= mu1_mu2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> t1, t2, t3;</div><div class="line"></div><div class="line">    t1 = 2 * mu1_mu2 + C1;</div><div class="line">    t2 = 2 * sigma12 + C2;</div><div class="line">    t3 = t1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(t2);                 <span class="comment">// t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))</span></div><div class="line"></div><div class="line">    t1 = mu1_2 + mu2_2 + C1;</div><div class="line">    t2 = sigma1_2 + sigma2_2 + C2;</div><div class="line">    t1 = t1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(t2);                 <span class="comment">// t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d3/d63/classcv_1_1Mat.html">Mat</a> ssim_map;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6db555d30115642fedae0cda05604874">divide</a>(t3, t1, ssim_map);        <span class="comment">// ssim_map =  t3./t1;</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d1/da0/classcv_1_1Scalar__.html">Scalar</a> mssim = <a class="code" href="../../d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461">mean</a>(ssim_map);   <span class="comment">// mssim = average of ssim map</span></div><div class="line">    <span class="keywordflow">return</span> mssim;</div><div class="line">}</div><div class="line"><span class="comment">// ![get-mssim]</span></div></div><!-- fragment -->  </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line"><span class="comment">#!/usr/bin/env python</span></div><div class="line"><span class="comment"># -*- coding: utf-8 -*-</span></div><div class="line"></div><div class="line"><span class="comment"># Python 2/3 compatibility</span></div><div class="line"><span class="keyword">from</span> __future__ <span class="keyword">import</span> print_function</div><div class="line"></div><div class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</div><div class="line"><span class="keyword">import</span> cv2 <span class="keyword">as</span> cv</div><div class="line"><span class="keyword">import</span> argparse</div><div class="line"><span class="keyword">import</span> sys</div><div class="line"></div><div class="line"><span class="comment"># [get-psnr]</span></div><div class="line"><span class="keyword">def </span>getPSNR(I1, I2):</div><div class="line">    s1 = <a class="code" href="../../d2/de8/group__core__array.html#ga6fef31bc8c4071cbc114a758a2b79c14">cv.absdiff</a>(I1, I2) <span class="comment">#|I1 - I2|</span></div><div class="line">    s1 = np.float32(s1)     <span class="comment"># cannot make a square on 8 bits</span></div><div class="line">    s1 = s1 * s1            <span class="comment"># |I1 - I2|^2</span></div><div class="line">    sse = s1.sum()          <span class="comment"># sum elements per channel</span></div><div class="line">    <span class="keywordflow">if</span> sse &lt;= 1e-10:        <span class="comment"># sum channels</span></div><div class="line">        <span class="keywordflow">return</span> 0            <span class="comment"># for small values return zero</span></div><div class="line">    <span class="keywordflow">else</span>:</div><div class="line">        shape = I1.shape</div><div class="line">        mse = 1.0 * sse / (shape[0] * shape[1] * shape[2])</div><div class="line">        psnr = 10.0 * np.log10((255 * 255) / mse)</div><div class="line">        <span class="keywordflow">return</span> psnr</div><div class="line"><span class="comment"># [get-psnr]</span></div><div class="line"></div><div class="line"><span class="comment"># [get-mssim]</span></div><div class="line"><span class="keyword">def </span>getMSSISM(i1, i2):</div><div class="line">    C1 = 6.5025</div><div class="line">    C2 = 58.5225</div><div class="line">    <span class="comment"># INITS</span></div><div class="line"></div><div class="line">    I1 = np.float32(i1) <span class="comment"># cannot calculate on one byte large values</span></div><div class="line">    I2 = np.float32(i2)</div><div class="line"></div><div class="line">    I2_2 = I2 * I2 <span class="comment"># I2^2</span></div><div class="line">    I1_2 = I1 * I1 <span class="comment"># I1^2</span></div><div class="line">    I1_I2 = I1 * I2 <span class="comment"># I1 * I2</span></div><div class="line">    <span class="comment"># END INITS</span></div><div class="line"></div><div class="line">    <span class="comment"># PRELIMINARY COMPUTING</span></div><div class="line">    mu1 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1, (11, 11), 1.5)</div><div class="line">    mu2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I2, (11, 11), 1.5)</div><div class="line"></div><div class="line">    mu1_2 = mu1 * mu1</div><div class="line">    mu2_2 = mu2 * mu2</div><div class="line">    mu1_mu2 = mu1 * mu2</div><div class="line"></div><div class="line">    sigma1_2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1_2, (11, 11), 1.5)</div><div class="line">    sigma1_2 -= mu1_2</div><div class="line"></div><div class="line">    sigma2_2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I2_2, (11, 11), 1.5)</div><div class="line">    sigma2_2 -= mu2_2</div><div class="line"></div><div class="line">    sigma12 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1_I2, (11, 11), 1.5)</div><div class="line">    sigma12 -= mu1_mu2</div><div class="line"></div><div class="line">    t1 = 2 * mu1_mu2 + C1</div><div class="line">    t2 = 2 * sigma12 + C2</div><div class="line">    t3 = t1 * t2                    <span class="comment"># t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))</span></div><div class="line"></div><div class="line">    t1 = mu1_2 + mu2_2 + C1</div><div class="line">    t2 = sigma1_2 + sigma2_2 + C2</div><div class="line">    t1 = t1 * t2                    <span class="comment"># t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))</span></div><div class="line"></div><div class="line">    ssim_map = <a class="code" href="../../d2/de8/group__core__array.html#ga1f96b569cac4c286642b34eff098138e">cv.divide</a>(t3, t1)    <span class="comment"># ssim_map =  t3./t1;</span></div><div class="line"></div><div class="line">    mssim = <a class="code" href="../../d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461">cv.mean</a>(ssim_map)       <span class="comment"># mssim = average of ssim map</span></div><div class="line">    <span class="keywordflow">return</span> mssim</div><div class="line"><span class="comment"># [get-mssim]</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">def </span>main():</div><div class="line">    parser = argparse.ArgumentParser()</div><div class="line">    parser.add_argument(<span class="stringliteral">&quot;-d&quot;</span>, <span class="stringliteral">&quot;--delay&quot;</span>, type=int, default=30, help=<span class="stringliteral">&quot; Time delay&quot;</span>)</div><div class="line">    parser.add_argument(<span class="stringliteral">&quot;-v&quot;</span>, <span class="stringliteral">&quot;--psnrtriggervalue&quot;</span>, type=int, default=30, help=<span class="stringliteral">&quot;PSNR Trigger Value&quot;</span>)</div><div class="line">    parser.add_argument(<span class="stringliteral">&quot;-r&quot;</span>, <span class="stringliteral">&quot;--ref&quot;</span>, type=str, default=<span class="stringliteral">&quot;Megamind.avi&quot;</span>, help=<span class="stringliteral">&quot;Path to reference video&quot;</span>)</div><div class="line">    parser.add_argument(<span class="stringliteral">&quot;-t&quot;</span>, <span class="stringliteral">&quot;--undertest&quot;</span>, type=str, default=<span class="stringliteral">&quot;Megamind_bugy.avi&quot;</span>,</div><div class="line">                        help=<span class="stringliteral">&quot;Path to the video to be tested&quot;</span>)</div><div class="line">    args = parser.parse_args()</div><div class="line"></div><div class="line">    sourceReference = args.ref</div><div class="line">    sourceCompareWith = args.undertest</div><div class="line">    delay = args.delay</div><div class="line">    psnrTriggerValue = args.psnrtriggervalue</div><div class="line"></div><div class="line">    framenum = -1 <span class="comment"># Frame counter</span></div><div class="line"></div><div class="line">    captRefrnc = <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv.VideoCapture</a>(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga4a37595bcd267558bd6c176c7307f050">cv.samples.findFileOrKeep</a>(sourceReference))</div><div class="line">    captUndTst = <a class="code" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv.VideoCapture</a>(<a class="code" href="../../d6/dba/group__core__utils__samples.html#ga4a37595bcd267558bd6c176c7307f050">cv.samples.findFileOrKeep</a>(sourceCompareWith))</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> <span class="keywordflow">not</span> captRefrnc.isOpened():</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;Could not open the reference &quot;</span> + sourceReference)</div><div class="line">        sys.exit(-1)</div><div class="line">    <span class="keywordflow">if</span> <span class="keywordflow">not</span> captUndTst.isOpened():</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;Could not open case test &quot;</span> + sourceCompareWith)</div><div class="line">        sys.exit(-1)</div><div class="line"></div><div class="line">    refS = (int(captRefrnc.get(cv.CAP_PROP_FRAME_WIDTH)), int(captRefrnc.get(cv.CAP_PROP_FRAME_HEIGHT)))</div><div class="line">    uTSi = (int(captUndTst.get(cv.CAP_PROP_FRAME_WIDTH)), int(captUndTst.get(cv.CAP_PROP_FRAME_HEIGHT)))</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> refS != uTSi:</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;Inputs have different size!!! Closing.&quot;</span>)</div><div class="line">        sys.exit(-1)</div><div class="line"></div><div class="line">    WIN_UT = <span class="stringliteral">&quot;Under Test&quot;</span></div><div class="line">    WIN_RF = <span class="stringliteral">&quot;Reference&quot;</span></div><div class="line"></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">cv.namedWindow</a>(WIN_RF, cv.WINDOW_AUTOSIZE)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga5afdf8410934fd099df85c75b2e0888b">cv.namedWindow</a>(WIN_UT, cv.WINDOW_AUTOSIZE)</div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">cv.moveWindow</a>(WIN_RF, 400, 0) <span class="comment">#750,  2 (bernat =0)</span></div><div class="line">    <a class="code" href="../../d7/dfc/group__highgui.html#ga8d86b207f7211250dbe6e28f76307ffb">cv.moveWindow</a>(WIN_UT, refS[0], 0) <span class="comment">#1500, 2</span></div><div class="line"></div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;Reference frame resolution: Width={} Height={} of nr#: {}&quot;</span>.format(refS[0], refS[1],</div><div class="line">                                                                             captRefrnc.get(cv.CAP_PROP_FRAME_COUNT)))</div><div class="line">    <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;PSNR trigger value {}&quot;</span>.format(psnrTriggerValue))</div><div class="line"></div><div class="line">    <span class="keywordflow">while</span> <span class="keyword">True</span>: <span class="comment"># Show the image captured in the window and repeat</span></div><div class="line">        _, frameReference = captRefrnc.read()</div><div class="line">        _, frameUnderTest = captUndTst.read()</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> frameReference <span class="keywordflow">is</span> <span class="keywordtype">None</span> <span class="keywordflow">or</span> frameUnderTest <span class="keywordflow">is</span> <span class="keywordtype">None</span>:</div><div class="line">            <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot; &lt; &lt; &lt;  Game over!  &gt; &gt; &gt; &quot;</span>)</div><div class="line">            <span class="keywordflow">break</span></div><div class="line"></div><div class="line">        framenum += 1</div><div class="line">        psnrv = getPSNR(frameReference, frameUnderTest)</div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;Frame: {}# {}dB&quot;</span>.format(framenum, round(psnrv, 3)), end=<span class="stringliteral">&quot; &quot;</span>)</div><div class="line"></div><div class="line">        <span class="keywordflow">if</span> (psnrv &lt; psnrTriggerValue <span class="keywordflow">and</span> psnrv):</div><div class="line">            mssimv = getMSSISM(frameReference, frameUnderTest)</div><div class="line">            <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>(<span class="stringliteral">&quot;MSSISM: R {}% G {}% B {}%&quot;</span>.format(round(mssimv[2] * 100, 2), round(mssimv[1] * 100, 2),</div><div class="line">                                                     round(mssimv[0] * 100, 2)), end=<span class="stringliteral">&quot; &quot;</span>)</div><div class="line"></div><div class="line">        <a class="code" href="../../df/d57/namespacecv_1_1dnn.html#a701210a0203f2786cbfd04b2bd56da47">print</a>()</div><div class="line"></div><div class="line">        <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(WIN_RF, frameReference)</div><div class="line">        <a class="code" href="../../df/d24/group__highgui__opengl.html#gaae7e90aa3415c68dba22a5ff2cefc25d">cv.imshow</a>(WIN_UT, frameUnderTest)</div><div class="line"></div><div class="line">        k = <a class="code" href="../../d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7">cv.waitKey</a>(delay)</div><div class="line">        <span class="keywordflow">if</span> k == 27:</div><div class="line">            <span class="keywordflow">break</span></div><div class="line"></div><div class="line">    sys.exit(0)</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordflow">if</span> __name__ == <span class="stringliteral">&quot;__main__&quot;</span>:</div><div class="line">    main()</div></div><!-- fragment -->  </div> <h2>How to read a video stream (online-camera or offline-file)? </h2>
<p>Essentially, all the functionalities required for video manipulation is integrated in the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a> C++ class. This on itself builds on the FFmpeg open source library. This is a basic dependency of OpenCV so you shouldn't need to worry about this. A video is composed of a succession of images, we refer to these in the literature as frames. In case of a video file there is a <em>frame rate</em> specifying just how long is between two frames. While for the video cameras usually there is a limit of just how many frames they can digitize per second, this property is less important as at any time the camera sees the current snapshot of the world.</p>
<p>The first task you need to do is to assign to a <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a> class its source. You can do this either via the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a57c0e81e83e60f36c83027dc2a188e80">cv::VideoCapture::VideoCapture</a> or its <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a614a1702e15f42ede5100014ce7f48ed">cv::VideoCapture::open</a> function. If this argument is an integer then you will bind the class to a camera, a device. The number passed here is the ID of the device, assigned by the operating system. If you have a single camera attached to your system its ID will probably be zero and further ones increasing from there. If the parameter passed to these is a string it will refer to a video file, and the string points to the location and name of the file. For example, to the upper source code a valid command line is: </p><div class="fragment"><div class="line">video/Megamind.avi video/Megamind_bug.avi  35 10</div></div><!-- fragment --><p> We do a similarity check. This requires a reference and a test case video file. The first two arguments refer to this. Here we use a relative address. This means that the application will look into its current working directory and open the video folder and try to find inside this the <em>Megamind.avi</em> and the <em>Megamind_bug.avi</em>. </p><div class="fragment"><div class="line"><span class="keyword">const</span> <span class="keywordtype">string</span> sourceReference = argv[1],sourceCompareWith = argv[2];</div><div class="line"></div><div class="line">VideoCapture captRefrnc(sourceReference);</div><div class="line"><span class="comment">// or</span></div><div class="line">VideoCapture captUndTst;</div><div class="line">captUndTst.open(sourceCompareWith);</div></div><!-- fragment --><p> To check if the binding of the class to a video source was successful or not use the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a9d2ca36789e7fcfe7a7be3b328038585">cv::VideoCapture::isOpened</a> function: </p><div class="fragment"><div class="line"><span class="keywordflow">if</span> ( !captRefrnc.isOpened())</div><div class="line">  {</div><div class="line">  cout  &lt;&lt; <span class="stringliteral">&quot;Could not open reference &quot;</span> &lt;&lt; sourceReference &lt;&lt; endl;</div><div class="line">  <span class="keywordflow">return</span> -1;</div><div class="line">  }</div></div><!-- fragment --><p> Closing the video is automatic when the objects destructor is called. However, if you want to close it before this you need to call its <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#afb4ab689e553ba2c8f0fec41b9344ae6">cv::VideoCapture::release</a> function. The frames of the video are just simple images. Therefore, we just need to extract them from the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html">cv::VideoCapture</a> object and put them inside a <em>Mat</em> one. The video streams are sequential. You may get the frames one after another by the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a473055e77dd7faa4d26d686226b292c1">cv::VideoCapture::read</a> or the overloaded &gt;&gt; operator: </p><div class="fragment"><div class="line">Mat frameReference, frameUnderTest;</div><div class="line">captRefrnc &gt;&gt; frameReference;</div><div class="line">captUndTst.read(frameUnderTest);</div></div><!-- fragment --><p> The upper read operations will leave empty the <em>Mat</em> objects if no frame could be acquired (either cause the video stream was closed or you got to the end of the video file). We can check this with a simple if: </p><div class="fragment"><div class="line"><span class="keywordflow">if</span>( frameReference.empty()  || frameUnderTest.empty())</div><div class="line">{</div><div class="line"> <span class="comment">// exit the program</span></div><div class="line">}</div></div><!-- fragment --><p> A read method is made of a frame grab and a decoding applied on that. You may call explicitly these two by using the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#ae38c2a053d39d6b20c9c649e08ff0146">cv::VideoCapture::grab</a> and then the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a9ac7f4b1cdfe624663478568486e6712">cv::VideoCapture::retrieve</a> functions.</p>
<p>Videos have many-many information attached to them besides the content of the frames. These are usually numbers, however in some case it may be short character sequences (4 bytes or less). Due to this to acquire these information there is a general function named <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#aa6480e6972ef4c00d74814ec841a2939">cv::VideoCapture::get</a> that returns double values containing these properties. Use bitwise operations to decode the characters from a double type and conversions where valid values are only integers. Its single argument is the ID of the queried property. For example, here we get the size of the frames in the reference and test case video file; plus the number of frames inside the reference. </p><div class="fragment"><div class="line"><a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a> refS = <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>((<span class="keywordtype">int</span>) captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dab26d2ba37086662261148e9fe93eecad">CAP_PROP_FRAME_WIDTH</a>),</div><div class="line">                 (int) captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dad8b57083fd9bd58e0f94e68a54b42b7e">CAP_PROP_FRAME_HEIGHT</a>)),</div><div class="line"></div><div class="line">cout &lt;&lt; <span class="stringliteral">&quot;Reference frame resolution: Width=&quot;</span> &lt;&lt; refS.<a class="code" href="../../d6/d50/classcv_1_1Size__.html#abfe0367b32c407ddccf5ddf92667c73d">width</a> &lt;&lt; <span class="stringliteral">&quot;  Height=&quot;</span> &lt;&lt; refS.height</div><div class="line">     &lt;&lt; <span class="stringliteral">&quot; of nr#: &quot;</span> &lt;&lt; captRefrnc.get(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704dadadc646b31cfd2194794a3a80b8fa6c2">CAP_PROP_FRAME_COUNT</a>) &lt;&lt; endl;</div></div><!-- fragment --><p> When you are working with videos you may often want to control these values yourself. To do this there is a <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a8c6d8c2d37505b5ca61ffd4bb54e9a7c">cv::VideoCapture::set</a> function. Its first argument remains the name of the property you want to change and there is a second of double type containing the value to be set. It will return true if it succeeds and false otherwise. Good examples for this is seeking in a video file to a given time or frame: </p><div class="fragment"><div class="line">captRefrnc.set(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da7c2fa550ba270713fca1405397b90ae0">CAP_PROP_POS_MSEC</a>, 1.2);  <span class="comment">// go to the 1.2 second in the video</span></div><div class="line">captRefrnc.set(<a class="code" href="../../d4/d15/group__videoio__flags__base.html#ggaeb8dd9c89c10a5c63c139bf7c4f5704da6223452891755166a4fd5173ea257068">CAP_PROP_POS_FRAMES</a>, 10); <span class="comment">// go to the 10th frame of the video</span></div><div class="line"><span class="comment">// now a read operation would read the frame at the set position</span></div></div><!-- fragment --><p> For properties you can read and change look into the documentation of the <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#aa6480e6972ef4c00d74814ec841a2939">cv::VideoCapture::get</a> and <a class="el" href="../../d8/dfe/classcv_1_1VideoCapture.html#a8c6d8c2d37505b5ca61ffd4bb54e9a7c">cv::VideoCapture::set</a> functions.</p>
<h3>Image similarity - PSNR and SSIM</h3>
<p>We want to check just how imperceptible our video converting operation went, therefore we need a system to check frame by frame the similarity or differences. The most common algorithm used for this is the PSNR (aka <b>Peak signal-to-noise ratio</b>). The simplest definition of this starts out from the <em>mean squared error</em>. Let there be two images: I1 and I2; with a two dimensional size i and j, composed of c number of channels.</p>
<p class="formulaDsp">
\[MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}\]
</p>
<p>Then the PSNR is expressed as:</p>
<p class="formulaDsp">
\[PSNR = 10 \cdot \log_{10} \left( \frac{MAX_I^2}{MSE} \right)\]
</p>
<p>Here the \(MAX_I\) is the maximum valid value for a pixel. In case of the simple single byte image per pixel per channel this is 255. When two images are the same the MSE will give zero, resulting in an invalid divide by zero operation in the PSNR formula. In this case the PSNR is undefined and as we'll need to handle this case separately. The transition to a logarithmic scale is made because the pixel values have a very wide dynamic range. All this translated to OpenCV and a function looks like:</p>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line"><span class="keywordtype">double</span> getPSNR(<span class="keyword">const</span> Mat&amp; I1, <span class="keyword">const</span> Mat&amp; I2)</div><div class="line">{</div><div class="line">    Mat s1;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6fef31bc8c4071cbc114a758a2b79c14">absdiff</a>(I1, I2, s1);       <span class="comment">// |I1 - I2|</span></div><div class="line">    s1.convertTo(s1, <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>);  <span class="comment">// cannot make a square on 8 bits</span></div><div class="line">    s1 = s1.mul(s1);           <span class="comment">// |I1 - I2|^2</span></div><div class="line"></div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a> s = <a class="code" href="../../d2/de8/group__core__array.html#ga716e10a2dd9e228e4d3c95818f106722">sum</a>(s1);        <span class="comment">// sum elements per channel</span></div><div class="line"></div><div class="line">    <span class="keywordtype">double</span> sse = s.val[0] + s.val[1] + s.val[2]; <span class="comment">// sum channels</span></div><div class="line"></div><div class="line">    <span class="keywordflow">if</span>( sse &lt;= 1e-10) <span class="comment">// for small values return zero</span></div><div class="line">        <span class="keywordflow">return</span> 0;</div><div class="line">    <span class="keywordflow">else</span></div><div class="line">    {</div><div class="line">        <span class="keywordtype">double</span> mse  = sse / (double)(I1.channels() * I1.total());</div><div class="line">        <span class="keywordtype">double</span> psnr = 10.0 * <a class="code" href="../../df/dfc/group__cudev.html#ga6d7f752d82c289caa24bbb5a278ac31d">log10</a>((255 * 255) / mse);</div><div class="line">        <span class="keywordflow">return</span> psnr;</div><div class="line">    }</div><div class="line">}</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line"><span class="keyword">def </span>getPSNR(I1, I2):</div><div class="line">    s1 = <a class="code" href="../../d2/de8/group__core__array.html#ga6fef31bc8c4071cbc114a758a2b79c14">cv.absdiff</a>(I1, I2) <span class="comment">#|I1 - I2|</span></div><div class="line">    s1 = np.float32(s1)     <span class="comment"># cannot make a square on 8 bits</span></div><div class="line">    s1 = s1 * s1            <span class="comment"># |I1 - I2|^2</span></div><div class="line">    sse = s1.sum()          <span class="comment"># sum elements per channel</span></div><div class="line">    <span class="keywordflow">if</span> sse &lt;= 1e-10:        <span class="comment"># sum channels</span></div><div class="line">        <span class="keywordflow">return</span> 0            <span class="comment"># for small values return zero</span></div><div class="line">    <span class="keywordflow">else</span>:</div><div class="line">        shape = I1.shape</div><div class="line">        mse = 1.0 * sse / (shape[0] * shape[1] * shape[2])</div><div class="line">        psnr = 10.0 * np.log10((255 * 255) / mse)</div><div class="line">        <span class="keywordflow">return</span> psnr</div></div><!-- fragment --> </div> <p>Typically result values are anywhere between 30 and 50 for video compression, where higher is better. If the images significantly differ you'll get much lower ones like 15 and so. This similarity check is easy and fast to calculate, however in practice it may turn out somewhat inconsistent with human eye perception. The <b>structural similarity</b> algorithm aims to correct this.</p>
<p>Describing the methods goes well beyond the purpose of this tutorial. For that I invite you to read the article introducing it. Nevertheless, you can get a good image of it by looking at the OpenCV implementation below.</p>
<dl class="section note"><dt>Note</dt><dd>SSIM is described more in-depth in the: "Z. Wang, A. C. Bovik, H. R. Sheikh and E. P.
    Simoncelli, "Image quality assessment: From error visibility to structural similarity," IEEE
    Transactions on Image Processing, vol. 13, no. 4, pp. 600-612, Apr. 2004." article.</dd></dl>
 <div class='newInnerHTML' title='cpp' style='display: none;'>C++</div><div class='toggleable_div label_cpp' style='display: none;'> <div class="fragment"><div class="line"></div><div class="line"><a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a> getMSSIM( <span class="keyword">const</span> Mat&amp; i1, <span class="keyword">const</span> Mat&amp; i2)</div><div class="line">{</div><div class="line">    <span class="keyword">const</span> <span class="keywordtype">double</span> C1 = 6.5025, C2 = 58.5225;</div><div class="line">    <span class="comment">/***************************** INITS **********************************/</span></div><div class="line">    <span class="keywordtype">int</span> d = <a class="code" href="../../d1/d1b/group__core__hal__interface.html#ga4a3def5d72b74bed31f5f8ab7676099c">CV_32F</a>;</div><div class="line"></div><div class="line">    Mat I1, I2;</div><div class="line">    i1.convertTo(I1, d);            <span class="comment">// cannot calculate on one byte large values</span></div><div class="line">    i2.convertTo(I2, d);</div><div class="line"></div><div class="line">    Mat I2_2   = I2.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I2);        <span class="comment">// I2^2</span></div><div class="line">    Mat I1_2   = I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I1);        <span class="comment">// I1^2</span></div><div class="line">    Mat I1_I2  = I1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(I2);        <span class="comment">// I1 * I2</span></div><div class="line"></div><div class="line">    <span class="comment">/*************************** END INITS **********************************/</span></div><div class="line"></div><div class="line">    Mat mu1, mu2;                   <span class="comment">// PRELIMINARY COMPUTING</span></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1, mu1, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I2, mu2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line"></div><div class="line">    Mat mu1_2   =   mu1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu1);</div><div class="line">    Mat mu2_2   =   mu2.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu2);</div><div class="line">    Mat mu1_mu2 =   mu1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(mu2);</div><div class="line"></div><div class="line">    Mat sigma1_2, sigma2_2, sigma12;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1_2, sigma1_2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma1_2 -= mu1_2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I2_2, sigma2_2, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma2_2 -= mu2_2;</div><div class="line"></div><div class="line">    <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">GaussianBlur</a>(I1_I2, sigma12, <a class="code" href="../../dc/d84/group__core__basic.html#ga346f563897249351a34549137c8532a0">Size</a>(11, 11), 1.5);</div><div class="line">    sigma12 -= mu1_mu2;</div><div class="line"></div><div class="line">    Mat t1, t2, t3;</div><div class="line"></div><div class="line">    t1 = 2 * mu1_mu2 + C1;</div><div class="line">    t2 = 2 * sigma12 + C2;</div><div class="line">    t3 = t1.<a class="code" href="../../d3/d63/classcv_1_1Mat.html#a385c09827713dc3e6d713bfad8460706">mul</a>(t2);                 <span class="comment">// t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))</span></div><div class="line"></div><div class="line">    t1 = mu1_2 + mu2_2 + C1;</div><div class="line">    t2 = sigma1_2 + sigma2_2 + C2;</div><div class="line">    t1 = t1.<a class="code" href="../../d1/d10/classcv_1_1MatExpr.html#a0e80cbf0fa6ed1187294697ab2b674ca">mul</a>(t2);                 <span class="comment">// t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))</span></div><div class="line"></div><div class="line">    Mat ssim_map;</div><div class="line">    <a class="code" href="../../d2/de8/group__core__array.html#ga6db555d30115642fedae0cda05604874">divide</a>(t3, t1, ssim_map);        <span class="comment">// ssim_map =  t3./t1;</span></div><div class="line"></div><div class="line">    <a class="code" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">Scalar</a> mssim = <a class="code" href="../../d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461">mean</a>(ssim_map);   <span class="comment">// mssim = average of ssim map</span></div><div class="line">    <span class="keywordflow">return</span> mssim;</div><div class="line">}</div></div><!-- fragment --> </div>  <div class='newInnerHTML' title='python' style='display: none;'>Python</div><div class='toggleable_div label_python' style='display: none;'> <div class="fragment"><div class="line"><span class="keyword">def </span>getMSSISM(i1, i2):</div><div class="line">    C1 = 6.5025</div><div class="line">    C2 = 58.5225</div><div class="line">    <span class="comment"># INITS</span></div><div class="line"></div><div class="line">    I1 = np.float32(i1) <span class="comment"># cannot calculate on one byte large values</span></div><div class="line">    I2 = np.float32(i2)</div><div class="line"></div><div class="line">    I2_2 = I2 * I2 <span class="comment"># I2^2</span></div><div class="line">    I1_2 = I1 * I1 <span class="comment"># I1^2</span></div><div class="line">    I1_I2 = I1 * I2 <span class="comment"># I1 * I2</span></div><div class="line">    <span class="comment"># END INITS</span></div><div class="line"></div><div class="line">    <span class="comment"># PRELIMINARY COMPUTING</span></div><div class="line">    mu1 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1, (11, 11), 1.5)</div><div class="line">    mu2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I2, (11, 11), 1.5)</div><div class="line"></div><div class="line">    mu1_2 = mu1 * mu1</div><div class="line">    mu2_2 = mu2 * mu2</div><div class="line">    mu1_mu2 = mu1 * mu2</div><div class="line"></div><div class="line">    sigma1_2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1_2, (11, 11), 1.5)</div><div class="line">    sigma1_2 -= mu1_2</div><div class="line"></div><div class="line">    sigma2_2 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I2_2, (11, 11), 1.5)</div><div class="line">    sigma2_2 -= mu2_2</div><div class="line"></div><div class="line">    sigma12 = <a class="code" href="../../d4/d86/group__imgproc__filter.html#gaabe8c836e97159a9193fb0b11ac52cf1">cv.GaussianBlur</a>(I1_I2, (11, 11), 1.5)</div><div class="line">    sigma12 -= mu1_mu2</div><div class="line"></div><div class="line">    t1 = 2 * mu1_mu2 + C1</div><div class="line">    t2 = 2 * sigma12 + C2</div><div class="line">    t3 = t1 * t2                    <span class="comment"># t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))</span></div><div class="line"></div><div class="line">    t1 = mu1_2 + mu2_2 + C1</div><div class="line">    t2 = sigma1_2 + sigma2_2 + C2</div><div class="line">    t1 = t1 * t2                    <span class="comment"># t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))</span></div><div class="line"></div><div class="line">    ssim_map = <a class="code" href="../../d2/de8/group__core__array.html#ga1f96b569cac4c286642b34eff098138e">cv.divide</a>(t3, t1)    <span class="comment"># ssim_map =  t3./t1;</span></div><div class="line"></div><div class="line">    mssim = <a class="code" href="../../d2/de8/group__core__array.html#ga191389f8a0e58180bb13a727782cd461">cv.mean</a>(ssim_map)       <span class="comment"># mssim = average of ssim map</span></div><div class="line">    <span class="keywordflow">return</span> mssim</div></div><!-- fragment --> </div> <p>This will return a similarity index for each channel of the image. This value is between zero and one, where one corresponds to perfect fit. Unfortunately, the many Gaussian blurring is quite costly, so while the PSNR may work in a real time like environment (24 frame per second) this will take significantly more than to accomplish similar performance results.</p>
<p>Therefore, the source code presented at the start of the tutorial will perform the PSNR measurement for each frame, and the SSIM only for the frames where the PSNR falls below an input value. For visualization purpose we show both images in an OpenCV window and print the PSNR and MSSIM values to the console. Expect to see something like:</p>
<div class="image">
<img src="../../outputVideoInput.png" alt="outputVideoInput.png"/>
</div>
<p>You may observe a runtime instance of this on the <a href="https://www.youtube.com/watch?v=iOcNljutOgg">YouTube here</a>.</p>
<div align='center'><iframe title='Video' width='560' height='349' src='https://www.youtube.com/embed/iOcNljutOgg?rel=0' frameborder='0' align='middle' allowfullscreen></iframe></div> </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:34 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
